package com.whh.starter.utils.json;

import cn.hutool.core.util.DesensitizedUtil;
import com.alibaba.fastjson.serializer.ValueFilter;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.*;
import java.util.function.UnaryOperator;

public class DesensitizedSerializeByFieldNameFilter implements ValueFilter {
    private static final Logger log = LoggerFactory.getLogger(DesensitizedSerializeByFieldNameFilter.class);
    @Override
    public Object process(Object o, String name, Object value) {
        try {
            if(!(value instanceof String)) {
                return value;
            }
            return FieldType.judgeType(name).desensitizedValue(value);
        } catch (Exception e) {
            log.error("desensitized error: {}", e.getMessage(), e);
            return value;
        }
    }

    enum FieldType {

        DEFAULT(new ArrayList<>(1), value -> value),
        MOBILE(Arrays.asList("mobile", "phone"), DesensitizedUtil::mobilePhone),
        FULL_NAME(Arrays.asList("fullName", "receiver","name","userName"), DesensitizedUtil::chineseName),
        ADDRESS(Collections.singletonList("address"), address -> DesensitizedUtil.address(address, address.length()/2)),
        EMAIL(Collections.singletonList("email"), DesensitizedUtil::email);

        private final List<String> fieldNameList;
        private final UnaryOperator<String> function;

        FieldType(List<String> fieldNameList, UnaryOperator<String> function) {
            this.fieldNameList = fieldNameList;
            this.function = function;
        }

        public static FieldType judgeType(String name) {
            FieldType[] fieldTypeList = FieldType.values();
            for(FieldType fieldType : fieldTypeList){
                if(fieldType.contains(name)){
                    return fieldType;
                }
            }
            return DEFAULT;
        }

        private boolean contains(String name) {
            if (StringUtils.isEmpty(name)) {
                return false;
            }
            return fieldNameList.contains(name);
        }

        private String desensitizedValue(Object value) {
            if (Objects.isNull(value) ) {
                return "";
            }
            return function.apply((String) value);
        }
    }
}
